﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Threading;
using System.Runtime.InteropServices;
using System.Diagnostics;

namespace HackBoy_Implementation
{
    public partial class Main : Form
    {
        [DllImport("kernel32.dll", EntryPoint = "GetTickCount", CharSet = CharSet.Auto, ExactSpelling = true)]
        public static extern uint GetTickCount();

        HackBoy HB;
        Thread tMiniBot;
        private bool bMiniBot = false;
        private bool bMiniBotInit = false;

        public Main()
        {
            InitializeComponent();
            HB = new HackBoy();
            tMiniBot = new Thread(new ThreadStart(MiniBotThread));
            tMiniBot.Start();
        }

        //delegate void addLogDelegate(string pMessage);
        delegate Int32 intDelegate();

        private void addLog(string pMessage)
        {
            if (txtBxLog.InvokeRequired)
            { //new addLogDelegate
                txtBxLog.Invoke((MethodInvoker)delegate { addLog(pMessage); });//, new object[] { pMessage });
            }
            else
            {
                DateTime dt = DateTime.Now;
                string dateTime = string.Format("{0:HH:mm:ss}", dt);
                this.txtBxLog.AppendText(dateTime + " : " + pMessage + "\r\n");
            }
        }

        private void btnPrintAgents_Click(object sender, EventArgs e)
        {
            addLog("Printing agent information please wait...");
            addLog(HB.PrintAgents());
            addLog("Done!");
        }

        private void btnRepairItems_Click(object sender, EventArgs e)
        {
            addLog("Repairing items please wait...");
            HB.RepairItems();
            addLog("Items repaired!");
        }

        private void btnGetQuestId_Click(object sender, EventArgs e)
        {
            addLog("Quest ID of selected quest in dialog is: " + HB.GetQuestID());
        }

        private void btnLootItem_Click(object sender, EventArgs e)
        {
            addLog("Looting nearest item pack please wait...");
            HB.LootItem();
            addLog("Looted the nearest item pack!");
        }

        private void btnGetTargetID_Click(object sender, EventArgs e)
        {
            addLog("Current target ID: " + HB.GetTargetID());
        }

        private void btnGetPartyInfo_Click(object sender, EventArgs e)
        {
            addLog("Printing party information please wait...");
            addLog(HB.GetPartyInfo());
            addLog("Done!");
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            txtBxAttackSkill.Enabled = bMiniBot;
            txtBxSkill1.Enabled = bMiniBot;
            txtBxSkill2.Enabled = bMiniBot;
            txtBxSkill1CD.Enabled = bMiniBot;
            txtBxSkill2CD.Enabled = bMiniBot;
            txtBxHpFood.Enabled = bMiniBot;
            txtBxMpFood.Enabled = bMiniBot;
            txtBxMobLock.Enabled = bMiniBot;
            txtBxKillQuest.Enabled = bMiniBot;
            btnGetCurrentTarget.Enabled = bMiniBot;
            chkBxLoot.Enabled = bMiniBot;
            chkBxRealmSwap.Enabled = bMiniBot;
            cmbBxPet.Enabled = bMiniBot;

            if(!bMiniBot)
            {
                btnStart.Text = "Stop";
                bMiniBotInit = false;
                addLog("Started bot");

                if (chkBxLoot.Checked)
                    HB.PS.Cmd(PipeCommands.CA_AutoLootOnOff, 1);
                else
                    HB.PS.Cmd(PipeCommands.CA_AutoLootOnOff, 0);
            }
            else
            {
                btnStart.Text = "Start";
                addLog("Stopped bot");
            }

            bMiniBot = !bMiniBot;
        }

        private void btnGetCurrentTarget_Click(object sender, EventArgs e)
        {
            txtBxMobLock.Text = HB.GetCurrentTargetName();
        }

        private Int32 TextToInt(String text)
        {
            if (text.Length == 0)
                return 0;
            return Convert.ToInt32(text);
        }

        private void MiniBotThread()
        {
            UInt32 tSkill1 = 0;
            UInt32 tSkill2 = 0;
            UInt32 tLastSkill = 0;
            UInt32 tHpFood = 0;
            UInt32 tMpFood = 0;
            UInt32 tEscape = 0;
            UInt32 tRealmChange = 0;
            UInt32 tKillQuest = 0;
            UInt32 tRepairGear = 0;

            Int32 AttackSkill = 0;
            Int32 Skill1 = 0;
            Int32 Skill2 = 0;
            Int32 Skill1CD = 0;
            Int32 Skill2CD = 0;
            Int32 HpFood = 0;
            Int32 MpFood = 0;
            Int32 PetIndex = 0;
            Int32 KillQuestSlot = 0;

            Int32 CurrentTarget = 0;
            Int32 MyId = 0;

            Random rnd = new Random();

            while (true)
            {
                if (bMiniBot)
                {
                    if (!bMiniBotInit)
                    {
                        try
                        {
                            CurrentTarget = 0;
                            MyId = HB.PS.CmdCB(PipeCommands.CA_GetMyId)[1].i;
                            AttackSkill = TextToInt(txtBxAttackSkill.Text);
                            KillQuestSlot = TextToInt(txtBxKillQuest.Text);
                            Skill1 = TextToInt(txtBxSkill1.Text);
                            Skill2 = TextToInt(txtBxSkill2.Text);
                            Skill1CD = TextToInt(txtBxSkill1CD.Text) * 1000;
                            Skill2CD = TextToInt(txtBxSkill2CD.Text) * 1000;
                            HpFood = TextToInt(txtBxHpFood.Text);
                            MpFood = TextToInt(txtBxMpFood.Text);

                            PetIndex = (Int32)cmbBxPet.Invoke((intDelegate)delegate
                            { return TextToInt(cmbBxPet.SelectedItem.ToString()); });
                        }
                        catch (Exception exception)
                        {
                            Debug.Print(exception.Message);
                        }
                        bMiniBotInit = true;
                    }

                    try
                    {
                        if (CurrentTarget == 0)
                        {
                            if ((float)(HB.PS.CmdCB(PipeCommands.CA_GetHp, MyId)[1].i / (float)HB.PS.CmdCB(PipeCommands.CA_GetHp, MyId)[2].i) > 0.10) //Over 10% HP
                            {
                                addLog("Attacking new target");
                                CurrentTarget = FindNextTarget();
                                HB.PS.Cmd(PipeCommands.CA_SelectTarget, CurrentTarget);
                                tEscape = GetTickCount();
                                do { Thread.Sleep(10); } while (HB.GetTargetID() != CurrentTarget || (GetTickCount() - tEscape) > 1000);
                                Thread.Sleep(100);
                                HB.PS.Cmd(PipeCommands.CA_UseSkill, AttackSkill);
                                tLastSkill = GetTickCount();
                            }
                        }

                        if (HB.GetTargetID() == CurrentTarget)
                        {
                            if ((GetTickCount() - tLastSkill) > 1000)
                            {
                                if ((GetTickCount() - tSkill1) > (Skill1CD + 500))
                                {
                                    if (Skill1 != 0)
                                    {
                                        HB.PS.Cmd(PipeCommands.CA_UseSkill, Skill1);
                                        tSkill1 = GetTickCount();
                                        tLastSkill = GetTickCount();
                                    }
                                }
                                else if ((GetTickCount() - tSkill2) > (Skill2CD + 500))
                                {
                                    if (Skill2 != 0)
                                    {
                                        HB.PS.Cmd(PipeCommands.CA_UseSkill, Skill2);
                                        tSkill2 = GetTickCount();
                                        tLastSkill = GetTickCount();
                                    }
                                }
                            }
                        }
                        else if (CurrentTarget != 0 && HB.PS.CmdCB(PipeCommands.CA_GetIsDead, CurrentTarget)[1].i == 0)
                        {
                            HB.PS.Cmd(PipeCommands.CA_SelectTarget, CurrentTarget);
                            tEscape = GetTickCount();
                            do { Thread.Sleep(10); } while (HB.GetTargetID() != CurrentTarget || (GetTickCount() - tEscape) > 1000);
                            Thread.Sleep(100);
                            HB.PS.Cmd(PipeCommands.CA_UseSkill, AttackSkill);
                            tLastSkill = GetTickCount();
                        }
                        else if (CurrentTarget != 0 && HB.PS.CmdCB(PipeCommands.CA_GetIsDead, CurrentTarget)[1].i == 1)
                        {
                            addLog("Target has been killed");
                            txtBxKillCount.Invoke((MethodInvoker)delegate
                            { txtBxKillCount.Text = (TextToInt(txtBxKillCount.Text) + 1).ToString(); });//txtBxKillCount.Text = (TextToInt(txtBxKillCount.Text) + 1).ToString();
                            //if (chkBxLoot.Checked)
                            //{
                            //    Thread.Sleep(200);
                            //    HB.PS.Cmd(PipeCommands.CA_LootItem);
                            //}
                            CurrentTarget = 0;

                            if (HB.PS.CmdCB(PipeCommands.CA_GetPetPlayerId)[1].i == 0)
                            {
                                HB.PS.Cmd(PipeCommands.CA_SummonPet, PetIndex);
                                Thread.Sleep(3000);
                            }
                        }

                        BaseMessage vitalStats = HB.PS.CmdCB(PipeCommands.CA_GetHp, MyId);
                        if (HpFood != 0)
                        {
                            if ((GetTickCount() - tHpFood) > 30500)
                            {
                                if (((float)vitalStats[1].i / (float)vitalStats[2].i) < 0.80) //80 %
                                {
                                    addLog("Using HP food");
                                    HB.PS.Cmd(PipeCommands.CA_UseItem, HpFood);
                                    tHpFood = GetTickCount();
                                }
                            }
                        }
                        if (MpFood != 0)
                        {
                            if ((GetTickCount() - tMpFood) > 30500)
                            {
                                if (((float)vitalStats[3].i / (float)vitalStats[4].i) < 0.80) //80 %
                                {
                                    addLog("Using MP food");
                                    HB.PS.Cmd(PipeCommands.CA_UseItem, MpFood);
                                    tMpFood = GetTickCount();
                                }
                            }
                        }

                        if ((GetTickCount() - tRealmChange) > 60 * 1000)
                        {
                            if (chkBxRealmSwap.Checked && ((float)vitalStats[1].i / (float)vitalStats[4].i) < 0.10) //10 %
                            {
                                Int32 newRealm = rnd.Next(1, 8);
                                if(newRealm == HB.PS.CmdCB(PipeCommands.CA_GetServerRealmInfo)[1].i)
                                {
                                    if(newRealm == 1)
                                        newRealm = 8;
                                    else
                                        newRealm--;
                                }
                                HB.PS.Cmd(PipeCommands.CA_ChangeRealm, newRealm);
                                tRealmChange = GetTickCount();
                                Thread.Sleep(5000);
                            }
                        }

                        if ((GetTickCount() - tKillQuest) > 60 * 1000)
                        {
                            if (KillQuestSlot != 0)
                            {
                                HB.PS.Cmd(PipeCommands.CA_UseItem, KillQuestSlot);
                                tKillQuest = GetTickCount();
                            }
                        }

                        if ((GetTickCount() - tRepairGear) > 10 * 60 * 1000)
                        {
                            HB.PS.Cmd(PipeCommands.CA_RepairItems);
                            tRepairGear = GetTickCount();
                        }
                    }
                    catch (Exception exception)
                    {
                        Debug.Print(exception.Message);
                    }
                }

                Thread.Sleep(50);
            }
        }

        private int FindNextTarget()
        {
            return HB.PS.CmdCB(PipeCommands.CA_GetClosestPlayerByName, txtBxMobLock.Text, 1 /* true */)[1].i;
        }

        private void btnRestartPipe_Click(object sender, EventArgs e)
        {
            if (!txtBxCharName.Text.Equals(""))
                HB.PS.sCharName = txtBxCharName.Text;
            HB.PS.Disconnect();
        }

        private void Main_FormClosing(object sender, FormClosingEventArgs e)
        {
            tMiniBot.Abort();
        }

        private void txtBxCharName_Enter(object sender, EventArgs e)
        {
            if (txtBxCharName.Text.Equals("Character Name"))
                txtBxCharName.Text = "";
        }

        private void txtBxMobLock_Enter(object sender, EventArgs e)
        {
            if (txtBxMobLock.Text.Equals("Mob Lock"))
                txtBxMobLock.Text = "";
        }
    }
}
